import java.util.Deque;
import java.util.ArrayDeque;
import java.util.Iterator;

class Polonaise
{
  private Deque<Shape> items;
  private Observable head;
  
  public Polonaise(Observable head)
  {
    if (head == null)
    {
      throw new IllegalArgumentException("head cannot be null");
    }
    this.head = head;
    this.items = new ArrayDeque<Shape>();
  }
  
  public Shape peekFirst()
  {
    return this.items.peekFirst();
  }
  
  public void detach(Shape shape)
  {
    Iterator<Shape> iterator = this.items.iterator();
    Observable next = this.head;
    while (iterator.hasNext())
    {
      Shape current = iterator.next();
      if (current == shape)
      {
        if (iterator.hasNext())
        {
          // make the previous shape follow the next shape
          Shape previous = iterator.next();
          FollowingMovementStrategy movementStrategy = new FollowingMovementStrategy(previous, next);
          previous.setMovementStrategy(movementStrategy);
        }
        break;
      }
      next = current;
    }
    this.items.remove(shape);
  }
  
  public void attach(Shape shape)
  {
    Observable lastItem = this.items.peekLast();
    if (lastItem == null)
    {
      lastItem = this.head;
    }
    FollowingMovementStrategy movementStrategy = new FollowingMovementStrategy(shape, lastItem);
    shape.setMovementStrategy(movementStrategy);
    this.items.addLast(shape);
  }
}
